import datetime
import time
import yaml
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select

# 读取配置文件
with open('config.yaml', 'r', encoding='utf-8') as config_file:
    config = yaml.safe_load(config_file)

NEW_PASSWORD = config["AppleMail"]["new_password"]
NEW_ANSWER1 = config["AppleMail"]["new_answer1"]
NEW_ANSWER2 = config["AppleMail"]["new_answer2"]
NEW_ANSWER3 = config["AppleMail"]["new_answer3"]

steps = []


# 读取txt文档中的数据
def read_data():
    with open("AppleMail.txt", "r", encoding='utf-8') as file:
        lines = file.readlines()
    return [line.strip() for line in lines]


# 删除已执行的前5行数据
def delete_executed_data():
    with open("AppleMail.txt", "r", encoding='utf-8') as file:
        lines = file.readlines()

    if len(lines) >= 5:
        with open("AppleMail.txt", "w", encoding='utf-8') as file:
            file.writelines(lines[5:])
    else:
        with open("AppleMail.txt", "w", encoding='utf-8') as file:
            file.writelines([])  # 删除所有的数据


# 执行登录操作
def login(email, password):
    try:
        options = webdriver.ChromeOptions()
        # 启用无痕浏览模式
        options.add_argument("--incognito")
        driver = webdriver.Chrome(options=options)
        driver.maximize_window()
        driver.get("https://appleid.apple.com/")
        # 点击登录按钮
        login_button = WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, "//button[contains(text(),'登录')]")))
        login_button.click()
        # 获取iframe元素
        el = WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="aid-auth-widget-iFrame"]')))
        # 切换iframe
        driver.switch_to.frame(el)
        # 填写邮箱
        email_input = WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="account_name_text_field"]')))
        email_input.send_keys(email)
        # 点击继续
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="sign-in"]'))).click()
        time.sleep(3)
        # 输入密码
        password_input = WebDriverWait(driver, 20).until(
            EC.visibility_of_element_located((By.XPATH, '//*[@id="password_text_field"]')))
        password_input.send_keys(password)
        # 点击继续
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="sign-in"]'))).click()
        # 等待页面加载完毕
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, "//h1[contains(text(),'回答你的安全提示问题以继续')]")))
        print("---------------------------------------------------------")
        steps.append("登录成功")
        print(f"邮箱名：{email}，登录成功")
        return driver
    except Exception:
        steps.append("登录失败")
        print(f"邮箱名：{email}，登录失败")
        raise


# 执行安全提示问题操作
def answer_security_questions(driver, answers):
    try:
        # 获取问题和答案的映射关系
        question_mapping = {
            "你少年时代最好的朋友叫什么名字？": answers[0],
            "你的理想工作是什么？": answers[1],
            "你的父母是在哪里认识的？": answers[2]
        }

        # 获取系统随机问的问题
        questions = driver.find_elements(By.XPATH, "//*[@class='sa-sk7__question']")
        question_texts = [question.text for question in questions]
        # 答案输入框
        answer_input = driver.find_elements(By.XPATH, "//*[@class='form-textbox-input']")
        # 填写问题答案
        for i, question_text in enumerate(question_texts):
            answer = question_mapping[question_text]
            answer_input[i].send_keys(answer)
        # 点击继续按钮
        continue_button = driver.find_element(By.XPATH, "//button[contains(text(), '继续')]")
        continue_button.click()
        # 获取iframe元素
        el = WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//iframe[@title="Apple ID 修复"]')))
        # 切换iframe
        driver.switch_to.frame(el)

        # 点击其他选项
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located(
                (By.XPATH, '//div[@class="primary-button-group"]/button[2]'))).click()

        time.sleep(0.5)
        # 点击不升级
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located(
                (By.XPATH, '//div[@class="primary-button-group"]/button[2]'))).click()

        driver.switch_to.default_content()
        steps.append("验证密保成功")
        print("验证密保成功")
    except Exception:
        steps.append("验证密保失败")
        print("验证密保失败")
        raise


# 执行密码修改操作
def change_password(driver, current_password):
    try:
        # 等待页面加载完毕
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, "//h1[contains(text(), '登录和安全')]")))
        # 点击密码按钮
        password_button = driver.find_element(By.XPATH, "//h3[contains(text(), '密码')]")
        password_button.click()
        # 等待弹窗加载完毕
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, "//h3[contains(text(), '更改密码')]")))

        # 输入当前密码、新密码和确认新密码
        current_password_input = driver.find_element(By.XPATH, '//form[@class="modal-form"]/div/div/div/div[1]/input')
        current_password_input.send_keys(current_password)
        time.sleep(0.5)
        new_password_input = driver.find_element(By.XPATH,
                                                 '//form[@class="modal-form"]/div/div/div/div[2]/div/div[2]/input')
        new_password_input.send_keys(NEW_PASSWORD)
        time.sleep(0.5)
        confirm_password_input = driver.find_element(By.XPATH, '//form[@class="modal-form"]/div/div/div/div[3]/input')
        confirm_password_input.send_keys(NEW_PASSWORD)
        time.sleep(0.5)

        # 点击更改密码按钮
        change_password_button = driver.find_element(By.XPATH,
                                                     '//form[@class="modal-form"]/div/fieldset/div/div[2]/button')
        change_password_button.click()

        # 等待密码修改成功提示出现
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, "//*[contains(text(), '你的密码已更改。')]")))

        # 等待密码修改完毕
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, "//span[contains(text(), '你的密码已更改')]")))

        # 关闭弹窗
        close_button = driver.find_element(By.XPATH, '//button[@aria-label="关闭"]')
        close_button.click()
        steps.append("修改密码成功")
        print("修改密码成功")
    except Exception:
        steps.append("修改密码失败")
        print("修改密码失败")
        raise

    # 执行安全提示问题修改操作


def change_security_questions(driver):
    try:
        # 等待登录和安全可见
        WebDriverWait(driver, 20).until(
            EC.visibility_of_element_located((By.XPATH, "//h1[contains(text(), '登录和安全')]")))

        # 点击账户安全按钮
        account_security_button = driver.find_element(By.XPATH, "//h3[contains(text(), '账户安全')]")
        account_security_button.click()

        # 等待弹窗加载完毕
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, "//h1[contains(text(), '账户安全')]")))

        # 点击更改安全提示问题按钮
        change_questions_button = driver.find_element(By.XPATH, "//button[contains(text(), '更改安全提示问题')]")
        change_questions_button.click()
        # 等待弹窗加载完毕
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, "//h1[contains(text(), '选择新的安全提示问题')]")))

        question_select = driver.find_elements(By.XPATH, '//form[@class="modal-form"]//select')
        # 选择问题1和填写答案1
        # 创建Select对象
        select1 = Select(question_select[0])
        # 通过文本值选择选项1
        select1.select_by_visible_text('你少年时代最好的朋友叫什么名字？')
        # 填写答案1
        answer_input1 = driver.find_element(By.XPATH, '//form[@class="modal-form"]/div[1]/div/div[2]/div/input')
        answer_input1.send_keys(NEW_ANSWER1)
        time.sleep(0.5)
        # 选择问题2和填写答案2
        # 创建Select对象
        select2 = Select(question_select[1])
        # 通过文本值选择选项2
        select2.select_by_visible_text('你的理想工作是什么？')
        # 填写答案2
        answer_input2 = driver.find_element(By.XPATH, '//form[@class="modal-form"]/div[1]/div/div[4]/div/input')
        answer_input2.send_keys(NEW_ANSWER2)
        time.sleep(0.5)
        # 选择问题3和填写答案3
        # 创建Select对象
        select3 = Select(question_select[2])
        # 通过文本值选择选项3
        select3.select_by_visible_text('你的父母是在哪里认识的？')
        # 填写答案3
        answer_input3 = driver.find_element(By.XPATH, '//form[@class="modal-form"]/div[1]/div/div[6]/div/input')
        answer_input3.send_keys(NEW_ANSWER3)
        time.sleep(0.5)
        # 点击更新按钮
        update_button = driver.find_element(By.XPATH, "//button[contains(text(), '更新')]")
        update_button.click()

        # 等待弹窗加载完毕
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, "//h1[contains(text(), '确认你的密码')]")))
        time.sleep(0.5)

        # 输入确认密码
        confirm_password_input = driver.find_element(By.XPATH, '//div[@class="form-textbox"]/input')
        confirm_password_input.send_keys(NEW_PASSWORD)

        # 点击继续按钮
        continue_button = driver.find_element(By.XPATH, "//button[contains(text(), '继续')]")
        continue_button.click()

        # 等待安全提示问题修改成功提示出现
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, "//h1[contains(text(), '安全提示问题已更改')]")))

        # 点击完成按钮
        finish_button = driver.find_element(By.XPATH, "//button[contains(text(), '完成')]")
        finish_button.click()

        # 点击窗口关闭按钮
        window_close_button = driver.find_element(By.XPATH, '//button[@aria-label="关闭"]')
        window_close_button.click()

        # 等待登录和安全可见
        WebDriverWait(driver, 20).until(
            EC.visibility_of_element_located((By.XPATH, "//h1[contains(text(), '登录和安全')]")))
        steps.append("修改密保成功")
        print("修改密保成功")
    except Exception:
        steps.append("修改密保失败")
        print("修改密保失败")
        raise

    # 点击退出登录按钮
    logout_button = driver.find_element(By.XPATH, '//a[@title="退出登录"]')
    logout_button.click()
    print("退出登录")
    driver.quit()


# 执行自动化测试
def run_test():
    global steps
    data = read_data()[:5]  # 读取前5行数据
    for line in data:
        try:
            # 解析数据
            # email, password, answer1, answer2, answer3, _, _, _ = line.split("----")
            str1 = line.split("----")
            answers = [str1[2], str1[3], str1[4]]

            # 执行登录操作
            driver = login(str1[0], str1[1])

            # 执行安全提示问题操作
            answer_security_questions(driver, answers)

            # 执行密码修改操作
            change_password(driver, str1[1])

            # 执行安全提示问题修改操作
            change_security_questions(driver)
            steps = []
        except Exception as e:
            # 记录错误信息
            with open("error.txt", "a") as file:
                file.write(f"{datetime.datetime.now()}:{line}----{type(e).__name__}Exception\n")
                file.write(f"发生错误时执行的步骤：{steps}\n")
                steps = []

    # 删除已执行的前5行数据
    delete_executed_data()


if __name__ == '__main__':
    run_test()
    pass
